home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / lpmud312.tar / lpmud312 / object.c < prev    next >
C/C++ Source or Header  |  1992-01-21  |  20KB  |  887 lines

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #ifdef __STDC__
  6. #include <memory.h>
  7. #endif
  8.  
  9. #include "lint.h"
  10. #include "interpret.h"
  11. #include "object.h"
  12. #include "sent.h"
  13. #include "config.h"
  14. #include "wiz_list.h"
  15. #include "exec.h"
  16.  
  17. extern int d_flag;
  18. extern int total_num_prog_blocks, total_prog_block_size;
  19.  
  20. #ifdef USE_TIOCGETP        /* Check if BSD */
  21. extern int getpid();
  22. #else
  23. extern pid_t getpid();
  24. #endif
  25.  
  26. extern char *xalloc PROT((int)), *string_copy PROT((char *));
  27.  
  28. void remove_swap_file PROT((struct object *));
  29.  
  30. extern int atoi();
  31.  
  32. struct object *previous_ob;
  33. extern struct svalue const0;
  34.  
  35. int tot_alloc_object, tot_alloc_object_size;
  36.  
  37. /*
  38.  * Replace newlines in a string with a carriage return, to make the string
  39.  * writeable on one line.
  40.  */
  41.  
  42. static void replace_newline(str)
  43.     char *str;
  44. {
  45.     for (; *str; str++) {
  46.     if (str[0] == '\n')
  47. #ifndef MSDOS
  48.         str[0] = '\r';
  49. #else
  50.         str[0] = 30;
  51. #endif
  52.     }
  53. }
  54.  
  55. /*
  56.  * Replace carriage return in a string with newlines.
  57.  */
  58.  
  59. static void restore_newline(str)
  60.     char *str;
  61. {
  62.     for (; *str; str++) {
  63. #ifndef MSDOS
  64.     if (str[0] == '\r')
  65. #else
  66.     if (str[0] == 30)
  67. #endif
  68.         str[0] = '\n';
  69.     }
  70. }
  71.  
  72. static int my_strlen(str)
  73.     char *str;
  74. {
  75.     int sz = 0;
  76.  
  77.     while (*str) {
  78.     sz++; 
  79.     if (*str == '\"' || *str == '\\') sz++;
  80.     str++;
  81.     }
  82.     return sz;
  83. }
  84.  
  85. /*
  86.  * Similar to strcat(), but escapes all funny characters.
  87.  * Used by save_object().
  88.  * src is modified temporarily, but restored again :-(
  89.  */
  90. static void my_strcat(dest,src)
  91.     char *dest,*src;
  92. {
  93.     char *pt,*pt2,ch[2];
  94.  
  95.     pt = strchr(src,'\\'); ch[1] = 0;
  96.     pt2 = strchr(src,'\"');
  97.     if (pt2 && pt2<pt || pt == 0)
  98.     pt = pt2;
  99.     while (pt) {
  100.     ch[0] = *pt; *pt = 0; 
  101.     strcat(dest,src); strcat(dest,"\\"); strcat(dest,ch);
  102.     src = pt+1; *pt = ch[0];
  103.     pt = strchr(src,'\\'); 
  104.     pt2 = strchr(src,'\"');
  105.     if (pt2 && pt2<pt || !pt)
  106.         pt = pt2;
  107.     }
  108.     strcat(dest,src);
  109. }
  110.     
  111.  
  112. static int save_size(v)
  113.      struct vector *v;
  114. {
  115.   int i,siz;
  116.   char numbuf[100];
  117.  
  118.   for (i=0, siz = 0; i < v->size; i++) {
  119.     if (v->item[i].type == T_STRING) {
  120.       siz += my_strlen(v->item[i].u.string) + 3; /* my_ */
  121.     }
  122.     else if (v->item[i].type == T_POINTER) {
  123.       siz += 2 + save_size(v->item[i].u.vec) + 2 + 1;
  124.     }
  125.     else if (v->item[i].type == T_NUMBER) {
  126.       sprintf(numbuf,"%d",v->item[i].u.number);
  127.       siz += strlen(numbuf) + 1;
  128.     }
  129.     else siz += 2;
  130.   }
  131.   return siz;
  132. }
  133.  
  134. /*
  135.  * Encode an array of elements into a contiguous string.
  136.  */
  137. static char *save_array(v)
  138.      struct vector *v;
  139. {
  140.     char *buf,*tbuf,numbuf[100];
  141.     int i;
  142.     
  143.     buf = xalloc(2+save_size(v)+2+1);
  144.     
  145.     strcpy(buf,"({");
  146.     for (i=0; i < v->size; i++) {
  147.     if (v->item[i].type == T_STRING) {
  148.         strcat(buf,"\""); my_strcat(buf,v->item[i].u.string); /* my_ */
  149.         strcat(buf,"\","); 
  150.     }
  151.     else if (v->item[i].type == T_POINTER) {
  152.         tbuf = save_array(v->item[i].u.vec);
  153.         strcat(buf,tbuf); strcat(buf,",");
  154.         free(tbuf);
  155.     }
  156.     else if (v->item[i].type == T_NUMBER) {
  157.         sprintf(numbuf,"%d,",v->item[i].u.number);
  158.         strcat(buf,numbuf);
  159.     }
  160.     else strcat(buf,"0,");    /* Objects can't be saved. */
  161.     }
  162.     strcat(buf,"})");
  163.     return buf;
  164. }
  165.  
  166. /*
  167.  * Save an object to a file.
  168.  * The routine checks with the function "valid_write()" in /obj/master.c
  169.  * to assertain that the write is legal.
  170.  */
  171. void save_object(ob, file)
  172.     struct object *ob;
  173.     char *file;
  174. {
  175.     char *name, tmp_name[80];
  176.     int len, i;
  177.     FILE *f;
  178.     int failed = 0;
  179.     /* struct svalue *v; */
  180.  
  181.     if (ob->flags & O_DESTRUCTED)
  182.     return;
  183. #ifdef COMPAT_MODE
  184.     if (ob->user) {
  185.     strcpy(tmp_name,ob->user->name);strcat(tmp_name,"/");
  186.     if (strncmp(file, "players/", 8) != 0 ||
  187.         strncmp(file+8, tmp_name, strlen(tmp_name)) != 0 ||
  188.         strchr(file, '.'))
  189.         {
  190.         error("Illegal save file name %s\n", file);
  191.         }
  192.     } else {
  193.     if (strncmp(current_prog->name, "obj/", 4) != 0 &&
  194.         strncmp(current_prog->name, "room/", 5) != 0 &&
  195.         strncmp(current_prog->name, "std/", 4) != 0) 
  196.         {
  197.         error("Illegal use of save_object()\n");
  198.         }
  199.     }
  200. #else
  201.     file = check_valid_path(file, ob->eff_user, "save_object", 1);
  202.     if (file == 0)
  203.     error("Illegal use of save_object()\n");
  204. #endif
  205.     len = strlen(file);
  206.     name = xalloc(len + 3);
  207.     (void)strcpy(name, file);
  208. #ifndef MSDOS
  209.     (void)strcat(name, ".o");
  210. #endif
  211.     /*
  212.      * Write the save-files to different directories, just in case
  213.      * they are on different file systems.
  214.      */
  215.     sprintf(tmp_name, "%s.tmp", name);
  216. #ifdef MSDOS
  217.     (void)strcat(name, ".o");
  218. #endif
  219.     f = fopen(tmp_name, "w");
  220.     if (f == 0) {
  221.     free(name);
  222.     error("Could not open %s for a save.\n", tmp_name);
  223.     }
  224.     for (i=0; i < ob->prog->num_variables; i++) {
  225.     struct svalue *v = &ob->variables[i];
  226.     char *new_string;
  227.  
  228.     if (ob->prog->variable_names[i].type & TYPE_MOD_STATIC)
  229.         continue;
  230.     if (v->type == T_NUMBER) {
  231.         if (fprintf(f, "%s %d\n", ob->prog->variable_names[i].name,
  232.             v->u.number) == EOF)
  233.         failed = 1;
  234.     } else if (v->type == T_STRING) {
  235.         new_string = string_copy(v->u.string);
  236.         replace_newline(new_string);
  237.         if (fprintf(f, "%s \"%s\"\n", ob->prog->variable_names[i].name,
  238.             new_string) == EOF)
  239.         failed = 1;
  240.         free(new_string);
  241.  
  242. /* Saving of arrays: JnA 910520
  243. */
  244.     } else if (v->type == T_POINTER) {
  245.         new_string = save_array(v->u.vec);
  246.         replace_newline(new_string);
  247.         if (fprintf(f, "%s %s\n", ob->prog->variable_names[i].name,
  248.             new_string) == EOF)
  249.             failed = 1;
  250.         free(new_string);
  251.     }
  252.     }
  253.     (void)unlink(name);
  254. #ifndef MSDOS
  255.     if (link(tmp_name, name) == -1)
  256. #else
  257.     (void) fclose(f);
  258.     if (rename(tmp_name,name) < 0)
  259. #endif
  260.     {
  261.     perror(name);
  262.     printf("Failed to link %s to %s\n", tmp_name, name);
  263.     add_message("Failed to save object !\n");
  264.     }
  265. #ifndef MSDOS
  266.     (void)fclose(f);
  267.     unlink(tmp_name);
  268. #endif
  269.     free(name);
  270.     if (failed)
  271.     add_message("Failed to save to file. Disk could be full.\n");
  272. }
  273.  
  274. static char *my_string_copy(str)
  275.     char *str;
  276. {
  277.     char *apa,*cp;
  278.  
  279.     cp = apa = xalloc(strlen(str)+1);
  280.     
  281.     while(*str) {
  282.     if (*str == '\\') {
  283.         *cp = str[1];
  284.         if (str[1]) str+=2;
  285.         else str++;   /* String ends with a \\ buggy probably */
  286.         cp++;
  287.     }
  288.     else { *cp = *str; cp++; str++; }
  289.     }
  290.     *cp=0;
  291.     cp = string_copy(apa);
  292.     free(apa);
  293.     return cp;
  294. }
  295.  
  296. /*
  297.  * Find the size of an array. Return -1 for failure.
  298.  */
  299. static int restore_size(str)
  300.      char **str;
  301. {
  302.   char *pt,*pt2;
  303.   int siz,tsiz;
  304.  
  305.   pt = *str; 
  306.   if (strncmp(pt,"({",2)) return -1;
  307.   else pt += 2;
  308.   siz = 0;
  309.  
  310.   while ((pt) && (*pt)) {
  311.     if (pt[0] == '}') {
  312.       if (pt[1] != ')') return -1;
  313.       *str = &pt[2];
  314.       return siz;
  315.     }
  316.     if (pt[0] == '\"') {
  317.       pt2 = strchr(&pt[1],'\"');
  318.       if (!pt2) return -1;
  319.       pt2--;
  320.       while (pt2[0] == '\\') {
  321.       pt = pt2;
  322.       pt2 = strchr(&pt[2],'\"');
  323.       if (!pt2) return -1;
  324.       pt2--;
  325.       }
  326.       if (pt2[2] != ',') return -1;
  327.       siz++;
  328.       pt = &pt2[3];
  329.     }
  330.     else if (pt[0] == '(') { 
  331.       tsiz = restore_size(&pt); /* Lazy way of doing it, a bit inefficient */
  332.       if (tsiz < 0)
  333.       return -1;
  334.       pt++;
  335.       siz++;
  336.     }
  337.     else {
  338.       pt2 = strchr(pt, ',');
  339.       if (!pt2)
  340.       return -1;
  341.       siz++;
  342.       pt = &pt2[1];
  343.     }
  344.   }
  345.   return -1;
  346. }
  347.  
  348. static struct vector *restore_array(str)
  349.      char **str;
  350. {
  351.   struct vector *v,*t;
  352.   char *pt,*pt2;
  353.   int i,siz;
  354.   
  355.   pt = *str; 
  356.   if (strncmp(pt,"({",2)) return 0;
  357.   pt2 = pt;
  358.   siz = restore_size(&pt2);
  359.   if (siz < 0) return 0;
  360.   v = allocate_array(siz);
  361.   pt+=2;
  362.  
  363.   for (i=0;i<siz;i++) {
  364.     if (!*pt) return v;
  365.     if (pt[0] == '\"') {
  366.       pt2 = strchr(&pt[1],'\"');
  367.       if (!pt2) return v;
  368.       pt2--;
  369.       while (pt2[0] == '\\') {
  370.       pt2 = strchr(&pt2[2],'\"');
  371.       if (!pt2) return v;
  372.       pt2--;
  373.       }
  374.       if (pt2[2] != ',') return v;
  375.       pt2[1] = 0;
  376.       v->item[i].type = T_STRING;
  377.       v->item[i].u.string = my_string_copy(pt+1); /* my_ */
  378.       v->item[i].string_type = STRING_MALLOC;
  379.       pt = &pt2[3];
  380.     }
  381.     else if (pt[0] == '(') {
  382.       t = restore_array(&pt);
  383.       if (!t) return v;
  384.       v->item[i].type = T_POINTER;
  385.       v->item[i].u.vec = t;
  386.       /* v->item[i].u.vec->ref++; marion - ref is already 1 (allocate_array) */
  387.       pt++;
  388.     }
  389.     else {
  390.       pt2 = strchr(pt,',');
  391.       if (!pt2) return v;
  392.       pt2[0] = 0;
  393.       v->item[i].type = T_NUMBER;
  394.       sscanf(pt,"%d",&(v->item[i].u.number));
  395.       pt = &pt2[1];
  396.     }
  397.   }
  398.   if (strncmp(pt,"})",2)) return v;
  399.   *str = &pt[2];
  400.   return v;
  401. }
  402.  
  403. int restore_object(ob, file)
  404.     struct object *ob;
  405.     char *file;
  406. {
  407.     char *name, var[100], *val, *buff, *space;
  408.     int len;
  409.     FILE *f;
  410.     struct object *save = current_object;
  411.     struct stat st;
  412.     struct variable *p;
  413.  
  414.     if (current_object != ob)
  415.     fatal("Bad argument to restore_object()\n");
  416.     if (ob->flags & O_DESTRUCTED)
  417.     return 0;
  418.  
  419. #ifndef COMPAT_MODE
  420.     file = check_valid_path(file, ob->eff_user, "restore_object", 0);
  421.     if (file == 0)
  422.     error("Illegal use of restore_object()\n");
  423. #endif
  424.  
  425.     len = strlen(file);
  426.     name = xalloc(len + 3);
  427.     (void)strcpy(name, file);
  428.     if (name[len-2] == '.' && name[len-1] == 'c')
  429.     name[len-1] = 'o';
  430.     else
  431.     (void)strcat(name, ".o");
  432.     f = fopen(name, "r");
  433.     if (!f || fstat(fileno(f), &st) == -1) {
  434.     free (name);
  435.     if (f) 
  436.         (void)fclose(f);
  437.     return 0;
  438.     }
  439.     if (st.st_size == 0) {
  440.     (void)fclose(f);
  441.     free (name);
  442.     return 0;
  443.     }
  444.     val = xalloc(st.st_size + 1);
  445.     buff = xalloc(st.st_size + 1);
  446.     current_object = ob;
  447.     while(1) {
  448.     struct svalue *v;
  449.  
  450.     if (fgets(buff, st.st_size + 1, f) == 0)
  451.         break;
  452.     /* Remember that we have a newline at end of buff ! */
  453.     space = strchr(buff, ' ');
  454.     if (space == 0 || space - buff >= sizeof (var)) {
  455.         (void)fclose(f);
  456.         error("Illegal format when restore %s.\n", name);
  457.     }
  458.     (void)strncpy(var, buff, space - buff);
  459.     var[space - buff] = '\0';
  460.     (void)strcpy(val, space+1);
  461.     p = find_status(var, 0);
  462.     if (p == 0 || (p->type & TYPE_MOD_STATIC))
  463.         continue;
  464.     v = &ob->variables[p - ob->prog->variable_names];
  465.     if (val[0] == '"') {
  466.         val[strlen(val) - 2] = '\0';    /* Strip trailing "\n */
  467.         restore_newline(val+1);
  468.         free_svalue(v);
  469.         v->type = T_STRING;
  470.         v->u.string = string_copy(val+1);
  471.         v->string_type = STRING_MALLOC;
  472.         continue;
  473.     }
  474. /* Restore array: JnA 910520
  475. */
  476.     if (val[0] == '(') {
  477.         char *pt = val;
  478.         val[strlen(val) - 1] = '\0';    /* Strip trailing \n */
  479.         restore_newline(val+1);
  480.         free_svalue(v);
  481.         v->type = T_POINTER;
  482.         v->u.vec = restore_array(&pt);
  483.         if (!v->u.vec) {
  484.         *v = const0;
  485.         (void)fclose(f);
  486.            error("Illegal array format when restore %s.\n", name);
  487.         }
  488.         continue;
  489.     }
  490.  
  491.     free_svalue(v);
  492.     v->type = T_NUMBER;
  493.     v->u.number = atoi(val);
  494.     }
  495.     current_object = save;
  496.     if (d_flag > 1)
  497.     debug_message("Object %s restored from %s.\n", ob->name, name);
  498.     free(name);
  499.     free(buff);
  500.     free(val);
  501.     (void)fclose(f);
  502.     return 1;
  503. }
  504.  
  505. void tell_npc(ob, str)
  506.     struct object *ob;
  507.     char *str;
  508. {
  509.     push_constant_string(str);
  510.     (void)apply("catch_tell", ob, 1);
  511. }
  512.  
  513. /*
  514.  * Send a message to an object.
  515.  * If it is an interactive object, it will go to his
  516.  * screen. Otherwise, it will go to a local function
  517.  * catch_tell() in that object. This enables communications
  518.  * between players and NPC's, and between other NPC's.
  519.  */
  520. void tell_object(ob, str)
  521.     struct object *ob;
  522.     char *str;
  523. {
  524.     struct object *save_command_giver;
  525.  
  526.     if (ob->flags & O_DESTRUCTED)
  527.     return;
  528.     if (ob->interactive) {
  529.     save_command_giver = command_giver;
  530.     command_giver = ob;
  531.     add_message("%s", str);
  532.     command_giver = save_command_giver;
  533.     return;
  534.     }
  535.     tell_npc(ob, str);
  536. }
  537.  
  538. void free_object(ob, from)
  539.     struct object *ob;
  540.     char *from;
  541. {
  542.     struct sentence *s;
  543.  
  544.     ob->ref--;
  545.     if (d_flag > 1)
  546.     printf("Subtr ref to ob %s: %d (%s)\n", ob->name,
  547.               ob->ref, from);
  548.     if (ob->ref > 0)
  549.     return;
  550.     if (d_flag)
  551.     printf("free_object: %s.\n", ob->name);
  552.     if (!(ob->flags & O_DESTRUCTED)) {
  553.     /* This is fatal, and should never happen. */
  554.     fatal("FATAL: Object 0x%x %s ref count 0, but not destructed (from %s).\n",
  555.         ob, ob->name, from);
  556.     }
  557.     if (ob->interactive)
  558.     fatal("Tried to free an interactive object.\n");
  559.     /*
  560.      * If the program is freed, then we can also free the variable
  561.      * declarations.
  562.      */
  563.     if (ob->prog) {
  564.     tot_alloc_object_size -=
  565.         (ob->prog->num_variables - 1) * sizeof (struct svalue) +
  566.         sizeof (struct object);
  567.     free_prog(ob->prog, 1);
  568.     ob->prog = 0;
  569.     }
  570.     if (ob->swap_num != -1)
  571.     remove_swap_file(ob);
  572.     for (s = ob->sent; s;) {
  573.     struct sentence *next;
  574.     next = s->next;
  575.     free_sentence(s);
  576.     s = next;
  577.     }
  578.     if (ob->name) {
  579.     if (d_flag > 1)
  580.         debug_message("Free object %s\n", ob->name);
  581.     if (lookup_object_hash(ob->name) == ob)
  582.         fatal("Freeing object %s but name still in name table", ob->name);
  583.     free(ob->name);
  584.     ob->name = 0;
  585.     }
  586.     tot_alloc_object--;
  587.     free((char *)ob);
  588. }
  589.  
  590. void add_ref(ob, from)
  591.     struct object *ob;
  592.     char *from;
  593. {
  594.     ob->ref++;
  595.     if (d_flag > 1)
  596.     printf("Add reference to object %s: %d (%s)\n", ob->name,
  597.            ob->ref, from);
  598. }
  599.  
  600. /*
  601.  * Allocate an empty object, and set all variables to 0. Note that a
  602.  * 'struct object' already has space for one variable. So, if no variables
  603.  * are needed, we allocate a space that is smaller than 'struct object'. This
  604.  * unused (last) part must of course (and will not) be referenced.
  605.  */
  606. struct object *get_empty_object(num_var)
  607.     int num_var;
  608. {
  609.     static struct object NULL_object;
  610.     struct object *ob;
  611.     int size = sizeof (struct object) +
  612.     (num_var - !!num_var) * sizeof (struct svalue);
  613.     int i;
  614.  
  615.     tot_alloc_object++;
  616.     tot_alloc_object_size += size;
  617.     ob = (struct object *)xalloc(size);
  618.     /* marion
  619.      * Don't initialize via memset, this is incorrect. E.g. the bull machines
  620.      * have a (char *)0 which is not zero. We have structure assignment, so
  621.      * use it.
  622.      */
  623.     *ob = NULL_object;
  624.     ob->ref = 1;
  625.     ob->swap_num = -1;
  626.     for (i=0; i<num_var; i++)
  627.     ob->variables[i] = const0;
  628.     return ob;
  629. }
  630.  
  631. void remove_all_objects() {
  632.     struct object *ob;
  633.     struct svalue v;
  634.  
  635.     v.type = T_OBJECT;
  636.     while(1) {
  637.     if (obj_list == 0)
  638.         break;
  639.     ob = obj_list;
  640.     v.u.ob = ob;
  641.     destruct_object(&v);
  642.     if (ob == obj_list)
  643.         break;
  644.     }
  645.     remove_destructed_objects();
  646. }
  647.  
  648. #if 0
  649. /*
  650.  * For debugging purposes.
  651.  */
  652. void check_ob_ref(ob, from)
  653.     struct object *ob;
  654.     char *from;
  655. {
  656.     struct object *o;
  657.     int i;
  658.  
  659.     for (o = obj_list, i=0; o; o = o->next_all) {
  660.     if (o->inherit == ob)
  661.         i++;
  662.     }
  663.     if (i+1 > ob->ref) {
  664.     fatal("FATAL too many references to inherited object %s (%d) from %s.\n",
  665.           ob->name, ob->ref, from);
  666.     if (current_object)
  667.         fprintf(stderr, "current_object: %s\n", current_object->name);
  668.     for (o = obj_list; o; o = o->next_all) {
  669.         if (o->inherit != ob)
  670.         continue;
  671.         fprintf(stderr, "  %s\n", ob->name);
  672.     }
  673.     }
  674. }
  675. #endif /* 0 */
  676.  
  677. static struct object *hashed_living[LIVING_HASH_SIZE];
  678.  
  679. static int num_living_names, num_searches = 1, search_length = 1;
  680.  
  681. static int hash_living_name(str)
  682.     char *str;
  683. {
  684. #if 1
  685.     return hashstr(str, 100, LIVING_HASH_SIZE);
  686. #else
  687.     unsigned ret = 0;
  688.  
  689.     while(*str)
  690.     ret = ret * 2 + *str++;
  691.     return ret % LIVING_HASH_SIZE;
  692. #endif
  693. }
  694.  
  695. struct object *find_living_object(str, player)
  696.     char *str;
  697.     int player;
  698. {
  699.     struct object **obp, *tmp;
  700.     struct object **hl;
  701.  
  702.     num_searches++;
  703.     hl = &hashed_living[hash_living_name(str)];
  704.     for (obp = hl; *obp; obp = &(*obp)->next_hashed_living) {
  705.     search_length++;
  706.     if (player && !((*obp)->flags & O_ONCE_INTERACTIVE))
  707.         continue;
  708.     if (!((*obp)->flags & O_ENABLE_COMMANDS))
  709.         continue;
  710.     if (strcmp((*obp)->living_name, str) == 0)
  711.         break;
  712.     }
  713.     if (*obp == 0)
  714.     return 0;
  715.     /* Move the found ob first. */
  716.     if (obp == hl)
  717.     return *obp;
  718.     tmp = *obp;
  719.     *obp = tmp->next_hashed_living;
  720.     tmp->next_hashed_living = *hl;
  721.     *hl = tmp;
  722.     return tmp;
  723. }
  724.  
  725. void set_living_name(ob, str)
  726.     struct object *ob;
  727.     char *str;
  728. {
  729.     struct object **hl;
  730.  
  731.     if (ob->flags & O_DESTRUCTED)
  732.     return;
  733.     if (ob->living_name) {
  734.     remove_living_name(ob);
  735.     }
  736.     num_living_names++;
  737.     hl = &hashed_living[hash_living_name(str)];
  738.     ob->next_hashed_living = *hl;
  739.     *hl = ob;
  740.     ob->living_name = make_shared_string(str);
  741. #if 0    /* This is not a pretty way to find out if it is a wizard */
  742.     if (ob->interactive) {
  743.     struct svalue *v;
  744.     
  745.     v = apply("query_level", ob, 0);
  746.     if (v && v->type == T_NUMBER && v->u.number >= 21)
  747.         ob->flags |= O_IS_WIZARD;
  748.     }
  749. #endif
  750.     return;
  751. }
  752.  
  753. void remove_living_name(ob)
  754.     struct object *ob;
  755. {
  756.     struct object **hl;
  757.  
  758. #ifdef MUDWHO
  759.     sendmudwhologout(ob);
  760. #endif
  761.     num_living_names--;
  762.     if (!ob->living_name)
  763.     fatal("remove_living_name: no living name set.\n");
  764.     hl = &hashed_living[hash_living_name(ob->living_name)];
  765.     while(*hl) {
  766.     if (*hl == ob)
  767.         break;
  768.     hl = &(*hl)->next_hashed_living;
  769.     }
  770.     if (*hl == 0)
  771.     fatal("remove_living_name: Object named %s no in hash list.\n",
  772.           ob->living_name);
  773.     *hl = ob->next_hashed_living;
  774.     free_string(ob->living_name);
  775.     ob->next_hashed_living = 0;
  776.     ob->living_name = 0;
  777. }
  778.  
  779. void stat_living_objects() {
  780.     add_message("Hash table of living objects:\n");
  781.     add_message("-----------------------------\n");
  782.     add_message("%d living named objects, average search length: %4.2f\n",
  783.         num_living_names, (double)search_length / num_searches);
  784. }
  785.  
  786. void reference_prog (progp, from)
  787.     struct program *progp;
  788.     char *from;
  789. {
  790.     progp->ref++;
  791.     if (d_flag)
  792.     printf("reference_prog: %s ref %d (%s)\n",
  793.         progp->name, progp->ref, from);
  794. }
  795.  
  796. /*
  797.  * Decrement reference count for a program. If it is 0, then free the prgram.
  798.  * The flag free_sub_strings tells if the propgram plus all used strings
  799.  * should be freed. They normally are, except when objects are swapped,
  800.  * as we want to be able to read the program in again from the swap area.
  801.  * That means that strings are not swapped.
  802.  */
  803. void free_prog(progp, free_sub_strings)
  804.     struct program *progp;
  805.     int free_sub_strings;
  806. {
  807.     progp->ref--;
  808.     if (progp->ref > 0)
  809.     return;
  810.     if (d_flag)
  811.     printf("free_prog: %s\n", progp->name);
  812.     if (progp->ref < 0)
  813.     fatal("Negative ref count for prog ref.\n");
  814.     total_prog_block_size -= progp->total_size;
  815.     total_num_prog_blocks -= 1;
  816.     if (free_sub_strings) {
  817.     int i;
  818.  
  819.     /* Free all function names. */
  820.     for (i=0; i < progp->num_functions; i++)
  821.         if (progp->functions[i].name)
  822.         free_string(progp->functions[i].name);
  823.     /* Free all strings */
  824.     for (i=0; i < progp->num_strings; i++)
  825.         free_string(progp->strings[i]);
  826.     /* Free all variable names */
  827.     for (i=0; i < progp->num_variables; i++)
  828.         free_string(progp->variable_names[i].name);
  829.     /* Free all inherited objects */
  830.     for (i=0; i < progp->num_inherited; i++)
  831.         free_prog(progp->inherit[i].prog, 1);
  832.     free(progp->name);
  833.     }
  834.     free((char *)progp);
  835. }
  836.  
  837. void reset_object(ob, arg)
  838.     struct object *ob;
  839.     int arg;
  840. {
  841.     extern int current_time;
  842.  
  843.     /* Be sure to update time first ! */
  844.     ob->next_reset = current_time + TIME_TO_RESET/2 +
  845.     random_number(TIME_TO_RESET/2);
  846. #ifdef COMPAT_MODE
  847.     push_number(arg);
  848.     (void)apply("reset", ob, 1);
  849. #else
  850.     if (arg == 0) {
  851.     apply("__INIT", ob, 0);
  852.     apply("create", ob, 0);
  853.     } else {
  854.     apply("reset", ob, 0);
  855.     }
  856. #endif    
  857.     ob->flags |= O_RESET_STATE;
  858. }
  859.  
  860. /*
  861.  * If there is a shadow for this object, then the message should be
  862.  * sent to it. But only if catch_tell() is defined. Beware that one of the
  863.  * shadows may be the originator of the message, which means that we must
  864.  * not send the message to that shadow, or any shadows in the linked list
  865.  * before that shadow.
  866.  */
  867. int shadow_catch_message(ob, str)
  868.     struct object *ob;
  869.     char *str;
  870. {
  871.     if (!ob->shadowed)
  872.     return 0;
  873.     while(ob->shadowed != 0 && ob->shadowed != current_object)
  874.     ob = ob->shadowed;
  875.     while(ob->shadowing) {
  876.     if (function_exists("catch_tell", ob))
  877.     {
  878.         push_constant_string(str);
  879.         if (apply("catch_tell", ob, 1)) /* this will work, since we know the */
  880.         /* function is defined */
  881.         return 1;
  882.     }
  883.     ob = ob->shadowing;
  884.     }
  885.     return 0;
  886. }
  887.